library(mlbench)
library(ggplot2)
library(plotly)
library(tidyverse)
library(viridis)Gráficos interactivos en R
Introducción
En este seminario vamos a explorar cómo crear gráficos en R, comenzando por gráficos básicos en R base, luego avanzaremos hacia gráficos más complejos con ggplot2, y finalmente incorporaremos interactividad con plotly. Al final, generaremos un archivo HTML con todos los gráficos para compartir de forma fácil y visual los resultados.
¿En qué gráficos nos vamos a centrar?
Diagramas de barras (barplot)
Diagramas de cajas y bigotes (boxplots)
Gráficos de dispersión (scatterplot)
Carga de librerías
Comenzamos cargando todas las librerías necesarias:
Conjunto de datos
Utilizaremos el dataset Pima Indians Diabetes de la librería mlbench de R.
Este conjunto de datos contiene resultados de pruebas de diabetes recogidos por el Instituto Nacional de Diabetes y Enfermedades Digestivas y Renales de EE.UU. de una población de mujeres de al menos 21 años, de ascendencia india pima y residentes cerca de Phoenix, Arizona.
El objetivo del conjunto de datos es predecir si un paciente tiene o no diabetes, basándose en determinadas mediciones diagnósticas incluidas en el conjunto de datos. En la versión del conjunto de datos que vamos a usar, los valores anormales (como presión sanguínea de 0) se han puesto a NA (valor perdido).
data("PimaIndiansDiabetes2", package = "mlbench")
datos <- PimaIndiansDiabetes2
dim(datos)[1] 768 9
n <- dim(datos)[1]
p <- dim(datos)[2]El conjunto de datos cuenta con n= 768 observaciones y las siguientes 9 variables:
pregnant: Número de embarazos
glucose: Concentración plasmática de glucosa (prueba de tolerancia a la glucosa)
pressure: Tensión arterial diastólica (mm Hg)
triceps: Grosor del pliegue cutáneo del tríceps (mm)
insulin: 2-Hour serum insulin (mu U/ml)
mass: Índice de masa corporal (peso en kg/(altura en m)^2)
pedigree: Función de pedigrí de la diabetes
age: Edad (años)
diabetes: Factor que indica el resultado de la prueba de diabetes (neg/pos)
Veamos el formato de las variables:
str(datos)'data.frame': 768 obs. of 9 variables:
$ pregnant: num 6 1 8 1 0 5 3 10 2 8 ...
$ glucose : num 148 85 183 89 137 116 78 115 197 125 ...
$ pressure: num 72 66 64 66 40 74 50 NA 70 96 ...
$ triceps : num 35 29 NA 23 35 NA 32 NA 45 NA ...
$ insulin : num NA NA NA 94 168 NA 88 NA 543 NA ...
$ mass : num 33.6 26.6 23.3 28.1 43.1 25.6 31 35.3 30.5 NA ...
$ pedigree: num 0.627 0.351 0.672 0.167 2.288 ...
$ age : num 50 31 32 21 33 30 26 29 53 54 ...
$ diabetes: Factor w/ 2 levels "neg","pos": 2 1 2 1 2 1 2 1 2 2 ...
Algunas observaciones:
head(datos) pregnant glucose pressure triceps insulin mass pedigree age diabetes
1 6 148 72 35 NA 33.6 0.627 50 pos
2 1 85 66 29 NA 26.6 0.351 31 neg
3 8 183 64 NA NA 23.3 0.672 32 pos
4 1 89 66 23 94 28.1 0.167 21 neg
5 0 137 40 35 168 43.1 2.288 33 pos
6 5 116 74 NA NA 25.6 0.201 30 neg
Y un pequeño resumen inicial:
summary(datos) pregnant glucose pressure triceps
Min. : 0.000 Min. : 44.0 Min. : 24.00 Min. : 7.00
1st Qu.: 1.000 1st Qu.: 99.0 1st Qu.: 64.00 1st Qu.:22.00
Median : 3.000 Median :117.0 Median : 72.00 Median :29.00
Mean : 3.845 Mean :121.7 Mean : 72.41 Mean :29.15
3rd Qu.: 6.000 3rd Qu.:141.0 3rd Qu.: 80.00 3rd Qu.:36.00
Max. :17.000 Max. :199.0 Max. :122.00 Max. :99.00
NA's :5 NA's :35 NA's :227
insulin mass pedigree age diabetes
Min. : 14.00 Min. :18.20 Min. :0.0780 Min. :21.00 neg:500
1st Qu.: 76.25 1st Qu.:27.50 1st Qu.:0.2437 1st Qu.:24.00 pos:268
Median :125.00 Median :32.30 Median :0.3725 Median :29.00
Mean :155.55 Mean :32.46 Mean :0.4719 Mean :33.24
3rd Qu.:190.00 3rd Qu.:36.60 3rd Qu.:0.6262 3rd Qu.:41.00
Max. :846.00 Max. :67.10 Max. :2.4200 Max. :81.00
NA's :374 NA's :11
Gráficos en R base
Primero, vamos a empezar con la creación de gráficos básicos usando las funciones incorporadas en R.
Diagrama de barras
tabla_frecuencias <- table(datos$diabetes)
barplot(tabla_frecuencias, col = "lightblue")Vamos a añadirle algunos detalles:
barplot(tabla_frecuencias, # datos
main = "Diagrama de barras de diabetes",# Título
ylab = 'Frecuencia',# Nombre eje y
xlab='Diabetes',# Nombre eje x
legend = rownames(tabla_frecuencias),#Leyenda
col=c("maroon3","lightskyblue"))#ColoresBoxplot
Más información: https://r-charts.com/es/distribucion/funcion-boxplot/
boxplot(datos$glucose, horizontal = TRUE)boxplot(glucose ~ pregnant, data = datos,
col = rainbow(max(datos$pregnant)),
main = 'Boxplot de glucosa en función del número de embarazos')Diagrama de dispersión
plot(datos$glucose,datos$insulin)Podemos añadir más información al gráfico de dispersión puesto que sabemos que hay individuos con diabetes e individuos sin ella.
# Definición de colores
colores <- c("neg" = "maroon3", "pos" = "lightskyblue")
# Crea el gráfico
plot(datos$glucose, datos$insulin,
col = colores[datos$diabetes], # Colores según diabetes
pch = c(16,17)[datos$diabetes], # Tipo de punto
xlab = "Glucosa", # Etiqueta del eje x
ylab = "Insulina", # Etiqueta del eje y
main = "Gráfico de Glucosa vs Insulina") # Título del gráfico
# Agrega la leyenda
legend("topright", # Ubicación de la leyenda
legend = names(colores), # Nombres de los niveles de diabetes
col = colores, # Colores correspondientes
pch = c(16,17)[datos$diabetes], # Tipos de puntos
title = "Diabetes") # Título de la leyendaGráficos con ggplot2
ggplot2 es una de las bibliotecas más utilizadas para la creación de gráficos complejos y personalizables. Su sistema de “gramática de gráficos” facilita la creación de gráficos detallados y estilizados.
Diagrama de barras con ggplot2:
# Crear gráfico con ggplot2
diag_barr_gg <- ggplot(data = datos, aes(x = diabetes)) +
geom_bar(aes(fill = diabetes)) +
scale_fill_manual(values=c("maroon3", "lightskyblue"))+
labs(title = "Diagrama de barras de diabetes",
x = "Diabetes",
y = "Frecuencia") +
theme_minimal()
diag_barr_ggExplicación:
ggplot(data = datos, aes(x = diabetes))inicializa el gráfico y define que el eje x representa la variablediabetes.geom_bar(aes(fill = diabetes))añade un gráfico de barras y utiliza colores diferentes para cada nivel de diabetes.scale_fill_manual(values = c("maroon3", "lightskyblue"))personaliza los colores de las barras según los niveles de diabetes.labs(title = "Diagrama de barras de diabetes", x = "Diabetes", y = "Frecuencia")añade un título y etiquetas a los ejes del gráfico.theme_minimal()aplica un estilo simple y limpio al gráfico.
ggplotly() convierte un gráfico estático de ggplot2 en un gráfico interactivo
ggplotly(diag_barr_gg, tooltip = c("x", "y"))Con tooltip aclaramos lo que queremos que muestre el gráfico al pasar el ratón. En este caso, al poner (x,y), estamos indicando que queremos que nos muestre información sobre el eje x y el eje y.
Boxplot con ggplot2:
Comenzamos con un único boxplot:
boxplot_gg <- ggplot(datos, aes(x=glucose)) +
geom_boxplot(fill = 'purple',alpha=0.2) +
labs(title = "Boxplot de glucosa",
x = "Glucosa") +
theme_minimal() +
theme(axis.text.y = element_blank()) # Quitar el texto del eje y
boxplot_ggVamos ahora a graficar varios boxplots juntos para su comparación. En particular, estamos interesados en ver cómo cambia la glucosa en función del número de embarazos.
boxplot_pregnant_gg <- ggplot(datos,
aes(x=as.factor(pregnant),
y=glucose,
fill =as.factor(pregnant))) +
geom_boxplot(alpha=0.8) +
labs(title = "Boxplot de glucosa en función del nº de embarazos",
x = "Número de embarazos",y='Glucosa') +
scale_fill_viridis_d() + # Usa una paleta de colores de viridis
theme_minimal() +
theme(legend.position = "none")
boxplot_pregnant_ggggplotly(boxplot_pregnant_gg)Diagrama de dispersión con ggplot2:
scatter_gg <- ggplot(datos,
aes(y=insulin, x=glucose,
color=diabetes,
shape=diabetes)) +
geom_point(size=2.5) +
scale_color_manual(values=c("maroon3", "lightskyblue"))+
labs(title = "Diagrama de dispersión insulina vs glucosa",
x = "Glucosa",y='Insulina')+
theme_minimal()
scatter_ggggplotly(scatter_gg, tooltip = c("x","y"))Gráficos interactivos con plotly
plotly permite agregar interactividad a los gráficos, lo que resulta útil para exploración de datos y transmisión de información.
Diagrama de barras con plotly:
# Tabla de frecuencias
tabla <- as.data.frame(tabla_frecuencias)
colnames(tabla) <- c('diabetes','frecuencia')
# Crear el barplot en Plotly
grafico <- plot_ly(tabla, x = ~diabetes, y = ~frecuencia, type = 'bar',
marker = list(color = 'slateblue')) %>%
layout(title = "Diagrama de barras de diabetes",
xaxis = list(title = "Diabetes"),
yaxis = list(title = "Frecuencia"))
graficoPlotly permite personalizar el hover, es decir, el texto que aparece cuando pasamos el ratón:
# Tabla de frecuencias
tabla <- as.data.frame(tabla_frecuencias)
colnames(tabla) <- c('diabetes','frecuencia')
texto <- c('Sin diabetes','Con diabetes')
tabla$texto <- texto
# Crear el barplot en Plotly
grafico <- plot_ly(tabla, x = ~diabetes, y = ~frecuencia, type = 'bar',
marker = list(color = c("#CD2990", "lightskyblue")),
hovertemplate = paste(tabla$texto,
'<br> Frecuencia:', tabla$frecuencia,
'<extra></extra>')) %>%
layout(title = "Diagrama de barras de diabetes",
xaxis = list(title = "Diabetes"),
yaxis = list(title = "Frecuencia"))
graficoBoxplot con plotly:
fig <- plot_ly(datos,y = ~glucose, type = "box", hoverinfo='y') %>%
layout(title = 'Boxplot glucosa',
xaxis = list(title = "", showticklabels = FALSE),
yaxis = list(title = 'Glucosa'))
figSi además queremos visualizar los puntos, le añadimos boxpoints = "all", jitter = 0.5, pointpos = -1.8 :
fig <- plot_ly(datos,y = ~pressure, type = "box", hoverinfo='y',
boxpoints = "all", jitter = 0.5,
pointpos = -1.8) %>%
layout(title = 'Boxplot Presión',
xaxis = list(title = "", showticklabels = FALSE),
yaxis = list(title = 'Presión'))
figVisualicemos ahora varios boxplots juntos:
fig <- plot_ly(datos, y = ~glucose, color = ~as.factor(pregnant),
type = "box") %>%
layout(showlegend = FALSE,
title = "Boxplot de glucosa en función del número de embarazos",
xaxis = list(title = "Número de embarazos",
tickvals = 1:max(datos$pregnant)),
yaxis = list(title = "Glucosa"))
figDiagrama de dispersión con plotly:
fig <- plot_ly(data = datos, x = ~glucose, y = ~insulin,
color = ~diabetes,
colors = c("#CD2990", "lightskyblue"),
symbol = ~diabetes, symbols = c('x','s'),
marker = list(size = 8),
hovertemplate = paste('<b>Diabetes: </b>', datos$diabetes,
'<br> Insulina:', datos$insulin,
'<br> Glucosa:', datos$glucose,
'<extra></extra>'))
figSi además tuviéramos un identificador para cada elemento:
datos$ID <- seq(1,dim(datos)[1],1)
fig <- plot_ly(data = datos, x = ~glucose, y = ~insulin,
color = ~diabetes,
colors = c("#CD2990", "lightskyblue"),
symbol = ~diabetes, symbols = c('x','s'),
marker = list(size = 8),
hovertemplate = paste('<b>Diabetes: </b>', datos$diabetes,
'<br> Insulina:', datos$insulin,
'<br> Glucosa:', datos$glucose,
'<br>Paciente ID:', datos$ID,
'<extra></extra>'))
figMás y más y más
Gráficos ready to publish https://rpkgs.datanovia.com/ggpubr/
Series temporales interactivo https://mode.com/blog/r-data-visualization-packages#dygraphs
Gráficos conectados: https://x.com/RosanaFerrero/status/1833825018238640443